﻿using Microsoft.Win32;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using ScottPlot;
using ScottPlot.Drawing;
using ScottPlot.Plottable;
using System.IO;
using System.Windows.Media.Animation;
using System;

namespace CSV_DataViewer
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        class DataTag
        {
            public int id { get; set; }
            public SignalPlot plot { get; set; }
            public double max { get; set; }
            public double min { get; set; }
        }
        string[] Time { get; set; }
        double[][] Data { get; set; }
        Crosshair Crosshair { get; set; }
        Tooltip Tips { get; set; }
        public MainWindow()
        {
            InitializeComponent();
            series.MouseMove += Series_MouseMove;
            Crosshair = series.Plot.AddCrosshair(0, 0);
            series.Refresh();
        }
        private void Button_Select(object sender, RoutedEventArgs e)
        {
            GC.Collect();
            OpenFileDialog openFileDialog = new OpenFileDialog() { Filter="csv file|*.csv"};
            if (openFileDialog.ShowDialog() == true)
            {
                dataGrid.Visibility = Visibility.Collapsed;
                contentGrid.Visibility = Visibility.Visible;
                filepath.Text = openFileDialog.FileName;

                string[][] data = File.ReadAllText(openFileDialog.FileName).Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries).AsParallel().
                    Select(o => o.Split(new string[] { "," }, StringSplitOptions.None).ToArray()).ToArray();
                int dataline = Array.IndexOf(data, data.Take(20).Where(t => t.Length > 1 && !string.IsNullOrEmpty(t[0])).Skip(1).First());
                Data = data.Skip(dataline).AsParallel().Select(o => o.Select(x => {
                    double.TryParse(x, out double result);
                    return result;
                }).ToArray()).ToArray();
                Time = data.Skip(dataline).AsParallel().Select(o => o[0]).ToArray();
                var param = data.Take(20).Where(o => o.Length > 1).First().ToList();

                int index = 0;
                param.ForEach(o => {
                    if (double.TryParse(data[dataline][index], out double result))
                    {
                        StackPanel sp = new StackPanel()
                        {
                            Orientation = System.Windows.Controls.Orientation.Horizontal,
                            Tag = new DataTag { id = index, max = Data.Select(t => t[index]).Max(), min = Data.Select(t => t[index]).Min() }
                        };
                        var box = new CheckBox() { Content = o };
                        box.Checked += Box_Checked;
                        box.Unchecked += Box_Unchecked;
                        sp.Children.Add(box);
                        sp.Children.Add(new TextBlock()
                        {
                            Margin = new Thickness(30, 0, 0, 0),
                            Foreground = System.Windows.Media.Brushes.Red,
                            VerticalAlignment = System.Windows.VerticalAlignment.Center
                        });
                        check.Children.Add(sp);
                    }
                    index++;
                });
            }
        }
        private void Box_Unchecked(object sender, RoutedEventArgs e)
        {
            CheckBox it = sender as CheckBox;
            series.Plot.Remove(((it.Parent as StackPanel).Tag as DataTag).plot);
            series.Refresh();
        }

        private void Box_Checked(object sender, RoutedEventArgs e)
        {
            CheckBox it = sender as CheckBox;
            DataTag tag = (it.Parent as StackPanel).Tag as DataTag;
            var items = check.Children.Cast<StackPanel>().Where(o => (o.Children[0] as CheckBox).IsChecked ?? false);
            tag.plot = LoadPoints(Data.Select(o => o[tag.id]).ToArray(),
                items.Select(o => (o.Tag as DataTag).min).Min(),
                items.Select(o => (o.Tag as DataTag).max).Max(),
                it.Content as string);
            series.Refresh();
        }

        private void Series_MouseMove(object sender, MouseEventArgs e)
        {
            (double coordinateX, double coordinateY) = series.GetMouseCoordinates();
            Crosshair.X = coordinateX;
            Crosshair.Y = coordinateY;

            series.Plot.Remove(Tips);
            if (Time?.Length > coordinateX && coordinateX >= 0)
            {
                Tips = series.Plot.AddTooltip(string.Format("Time:{0}\r\nValue:{1}", Time[(int)coordinateX], coordinateY.ToString("0.000")), coordinateX, coordinateY);
                check.Children.Cast<StackPanel>().ToList().ForEach(it => {
                    if ((it.Children[0] as CheckBox).IsChecked ?? false){
                        DataTag tag = it.Tag as DataTag;
                        (it.Children[1] as TextBlock).Text = Data.Select(o => o[tag.id]).ToArray()[(int)coordinateX].ToString("0.000");
                    }else{
                        (it.Children[1] as TextBlock).Text = "";
                    }
                });
            }
            series.Refresh();
        }

        SignalPlot LoadPoints(double[] datas, double min, double max, string name)
        {
            var signal = series.Plot.AddSignal(datas, color: series.Plot.GetNextColor(), label: name);
            series.Plot.XAxis.SetBoundary(0, datas.Length);
            series.Plot.SetAxisLimitsX(0, datas.Length);

            series.Plot.YAxis.SetBoundary(min,max);
            if (min < max) series.Plot.SetAxisLimitsY(min, max);

            series.Plot.Legend(true, ScottPlot.Alignment.UpperRight);
            return signal;
        }

        private void Button_View(object sender, RoutedEventArgs e)
        {
            GC.Collect();
            OpenFileDialog openFileDialog = new OpenFileDialog() { Filter = "csv file|*.csv" };
            if (openFileDialog.ShowDialog() == true)
            {
                contentGrid.Visibility = Visibility.Collapsed;
                dataGrid.Visibility = Visibility.Visible;
                filepath.Text = openFileDialog.FileName;

                string[][] data = File.ReadAllText(openFileDialog.FileName).Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries).AsParallel().
                    Select(o => o.Split(new string[] { "," }, StringSplitOptions.None).ToArray()).ToArray();

                int index = 0;
                List<int> array_skip = new List<int>();
                System.Data.DataTable dt = new System.Data.DataTable();
                data.Where(o => o.Length > 1).First().ToList().ForEach(o => {
                    if (!dt.Columns.Contains(o))
                        dt.Columns.Add(o);
                    else
                        array_skip.Add(index);

                    index++;
                });
                int dataline = Array.IndexOf(data, data.Take(20).Where(t => t.Length > 1 && !string.IsNullOrEmpty(t[0])).Skip(1).First());
                data.Skip(dataline).ToList().ForEach(o => {
                    if (array_skip.Count > 0)
                        dt.Rows.Add(o.AsParallel().Where((t, i) => !array_skip.Contains(i)).ToArray());
                    else
                        dt.Rows.Add(o);
                });
                grid.ItemsSource = dt.DefaultView;
            }
        }
        private void dataGrid_LoadingRow(object sender, DataGridRowEventArgs e)
        {
            e.Row.Header = (e.Row.GetIndex() + 1).ToString();
        }
    }
}